package com.njupt.user.controller;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;

@ServerEndpoint("/chat/{userId}/{usertype}")
public class ChatServer {

	private Session session = null;
	//	private static Map<String,ChatServer> users = Collections.synchronizedMap(new HashMap());
	private String username;
	static private  Map<String ,  String> filePath  = new HashMap();

	//��ҳ�˵Ŀ�
	static private Map<String, html > htmlMap  = new HashMap();
	//���ӵĿ�
	static private Map<String, board> boardMap = new HashMap();


	public ChatServer(){
		System.out.println("WebsocketTest..");

//        htmlMap = new HashMap();
//        boardMap = new HashMap();
		System.out.println("******");
	}


	@OnOpen
	public void onOpen(Session session,@PathParam("userId") String username,@PathParam("usertype") String usertype){
		System.out.println("���ӳɹ�");

//        this.session = session;
//        System.out.println("sessionId="+session.getId());
//        System.out.println(session);

//        users.put(username,this);   //����map��,Ϊ�˲��Է���ʹ��username��key

		System.out.println(username);
		System.out.println(usertype);
		System.out.println("...............");
//        for(ChatServer m:users.values()) {
//
//        	System.out.println(m);
//        }


		//��������ʱ��ʼ����ҳ�˺Ͱ��ӵĿ�
		//��ҳ�˵Ŀ�
		if("1".equals(usertype)) {
			htmlMap.put(username, new html(username,"",session));
			html h = htmlMap.get(username);
			try {
//				h.getSession().getBasicRemote().sendText("hhhhhhhhhh");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println(h.getName());
			System.out.println(h.getSession());
			System.out.println(h.getBoardname());
		}
		else if("2".equals(usertype)) {
			//���ӵĿ�
			boardMap.put(username, new board(username,"",session));
			System.out.println(username);



		}
//      html h = htmlMap.get("html3");
//      System.out.println("h="+h);
//      board b = boardMap.get("board2");
//      System.out.println("b="+b);

	}
	@OnClose
	public void onClose(Session session,@PathParam("userId") String username,@PathParam("usertype") String usertype){
		this.session = session;
		System.out.println(this.session.getId()+"close....");
		System.out.println("close:"+username);
		//users.remove(username);

//		for(ChatServer m:users.values()) {
//
//		     System.out.println(m);
//		    }
//
//		}

		if("1".equals(usertype)) {
			htmlMap.remove(username);
			filePath.remove(username);
		}else if("2".equals(usertype)){
			boardMap.remove(username);
		}else {
			;
		}

	}
	@OnMessage
	/*
	 * ���ܿͻ��˷��͹�������Ϣ
	 */
	public void onMessage(Session session,String msg,@PathParam("userId") String username,@PathParam("usertype") String usertype){
		System.out.println("�ͻ��˷�����Ϣ��"+msg);
//        byte a[] = msg.getBytes();
//        for(byte t:a) {
//        	System.out.println(t);
//        }
//        System.out.println();


		//����usertype��ȷ����Ϣ������ҳ���ǰ��� 1����ҳ 2�ǰ���


		try {


			action_receive(session,msg,username,usertype);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}


	//ע��
	public void action_register() {

	}

	//ע��
	public void action_logout() {

	}

	private FileInputStream fileIn;
	private MappedByteBuffer mappedBuf;
	private long fileLength;
	private int arraySize;
	private byte[] array;

	//���ļ�
	public void action_sendFile(Session session,String username) throws IOException {

		System.out.println("23232323");
		short count = 0;

		board bo = boardMap.get(username);
		String htmlname = bo.getHtmlname();

		this.fileIn = new FileInputStream(filePath.get(htmlname).toString());
		FileChannel fileChannel = fileIn.getChannel();
		this.fileLength = fileChannel.size();
		this.mappedBuf = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileLength);
		this.arraySize = 1464; //data����

		int limit = mappedBuf.limit(); //�ļ��ܳ���

		int position = mappedBuf.position(); //��ʼλ��

		if (position == limit) {
			return ;
		}
		while (limit - mappedBuf.position() > this.arraySize) {

			this.array = new byte[this.arraySize];
			mappedBuf.get(this.array);

			//������Ϣ֡
			byte data[] = new byte[1472];
			data[0] = (Info.info_data<<4)|(Info.info_sendFile&0x0f);
			data[1] = (byte)(fileLength>>16); //��λ
			data[2] = (byte)(fileLength>>8);
			data[3] = (byte)fileLength;
			data[4] = (byte)(count>>8);
			data[5] = (byte)count;
			data[6] = (byte)(this.arraySize>>8);
			data[7] = (byte)this.arraySize;


			for(int i = 0; i < this.arraySize; i++) {
				data[i+8] = this.array[i];
			}


			ByteBuffer byteBuffer = ByteBuffer.allocate(1472);
			byteBuffer.put(data);
			byteBuffer.position(0);
			byteBuffer.limit(1472);

			//this.session.getBasicRemote().sendBinary(byteBuffer);


			board d = boardMap.get(username);
			d.getSession().getBasicRemote().sendBinary(byteBuffer);
			count++;

		}
		// ���һ�ζ�ȡ����

		int surplus = limit - mappedBuf.position();

		array = new byte[surplus];
		mappedBuf.get(array);
		byte data[] = new byte[surplus + 8];
		data[0] = (Info.info_data<<4)|(Info.info_sendFile&0x0f);
		data[1] = (byte)(fileLength>>16); //��λ
		data[2] = (byte)(fileLength>>8);
		data[3] = (byte)fileLength;
		data[4] = (byte)(count>>8);
		data[5] = (byte)count;
		data[6] = (byte)(surplus>>8);
		data[7] = (byte)surplus;

		for(int i = 0; i < surplus; i++) {
			data[i+8] = this.array[i];
		}

		ByteBuffer byteBuffer = ByteBuffer.allocate(surplus + 8);
		byteBuffer.put(data);
		byteBuffer.position(0);
		byteBuffer.limit(surplus + 8);
//		     this.session.getBasicRemote().sendBinary(byteBuffer);
		board d = boardMap.get(username);
		d.getSession().getBasicRemote().sendBinary(byteBuffer);
		this.fileIn.close();
	}

	//��¼
	static byte i=0;
	public void action_flash(String Str,String username) {

//		//������ʽ  Str =   ǰ8�ֽ� + ��Ϣ
//		byte b[] = Str.getBytes();
//		byte t[] = new byte[b.length-8];
//		for(int i=8; i<b.length; i++) {
//			t[i-8] = b[i];
//		}
//		String s = new String(t);
//		//��s��������Ϣ������ǰ�ˣ�
//		try {
//
//			board bo = boardMap.get(username);
//			String htmlname = bo.getHtmlname();
//
//			html h = htmlMap.get(htmlname);
//			h.getSession().getBasicRemote().sendText(s);
//
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}

		if(i==0){
			board bo = boardMap.get(username);
			String htmlname = bo.getHtmlname();

			html h = htmlMap.get(htmlname);
			try {
				h.getSession().getBasicRemote().sendText("Device #1 IDCODE is 020F10DD");
			} catch (IOException e) {
				e.printStackTrace();
			}

			i++;
		}else if(i==1){
			board bo = boardMap.get(username);
			String htmlname = bo.getHtmlname();

			html h = htmlMap.get(htmlname);
			try {
				h.getSession().getBasicRemote().sendText("configuring SRAM device(s)...");
			} catch (IOException e) {
				e.printStackTrace();
			}
			i++;
		}else if(i==2){
			board bo = boardMap.get(username);
			String htmlname = bo.getHtmlname();

			html h = htmlMap.get(htmlname);
			try {
				h.getSession().getBasicRemote().sendText("DONE");
			} catch (IOException e) {
				e.printStackTrace();
			}

			i = 0;
		}
	}


	public void ctrl_register(Session session) {
		//����:ctrlRegisterOK
		try {
			this.session.getBasicRemote().sendText("ctrlRegOK");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void ctrl_logout(Session session) {
		try {
			this.session.getBasicRemote().sendText("ctrlLogoutOK");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void ctrl_file(Session session,String filePath,String username) {
		try {

			ByteBuffer byteBuffer = ByteBuffer.allocate(4);
			byteBuffer.put((byte)19);
			//��ȡ�ļ�����
			System.out.println("ctrl_file = "+ filePath);
			FileInputStream fileIn = new FileInputStream(filePath);
			FileChannel fileChannel = fileIn.getChannel();
			long fileLength = fileChannel.size();
			System.out.println("�ļ����ȣ�"+ fileLength);
			byteBuffer.put((byte)(fileLength>>16));
			byteBuffer.put((byte)(fileLength>>8));
			byteBuffer.put((byte)fileLength);
			byteBuffer.position(0);
			byteBuffer.limit(4);

			System.out.println("22222");
///////////////////////////////////////////////////////////////////////�¸�ʽ
			html h = htmlMap.get(username);
			board d = boardMap.get(h.getBoardname());
			System.out.println(d.getName());
			d.getSession().getBasicRemote().sendBinary(byteBuffer);



			System.out.print("15151");
			fileIn.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void ctrl_flash(Session session,String username) {
		try {

			String  rtmp = 	"rtmp://localhost:1935/live/home";
			int length = rtmp.length();
			System.out.println("length"+length);

			short num = 0;
			int valid = length;
			byte []rt = rtmp.getBytes();
			System.out.println(rt.length);

			ByteBuffer byteBuffer = ByteBuffer.allocate(8+length+1);
			byteBuffer.put((byte) ((Info.info_ctrl<<4)|(Info.info_flash) ));
			byteBuffer.put((byte)(length>>16));
			byteBuffer.put((byte)(length>>8));
			byteBuffer.put((byte)length);
			byteBuffer.put((byte)0);
			byteBuffer.put((byte)0);
			byteBuffer.put((byte)(length>>8));
			byteBuffer.put((byte)length);
			byteBuffer.put(rt);
			byteBuffer.position(0);
			byteBuffer.limit(8+length+1);

			board b = boardMap.get(username);
			b.getSession().getBasicRemote().sendBinary(byteBuffer);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	//���ͺ���
	public void action_send() {

	}

	//�����ļ�·��
//    static private String filePath;

	//���պ���
	public void action_receive(Session session,String str,String username,String usertype) throws Exception {
		//�����ַ���



		String valid = null;
		String[] temp = str.split("#");

		if("1".equals(usertype)) {
			//������Ϣ֡      Ŀ���û�#��Ϣ
			String s = temp[0];
			//�޸İ��ӵĿ�
			System.out.println(username);
			System.out.println(s);
			System.out.println(temp[1]);
			System.out.println("~~~~~~~~~~");


			board b = boardMap.get(temp[0]);

			System.out.println(b);
			System.out.println(b.getName());

			b.setHtmlname(username); //��Ҫ���ʵİ��ӵĿ���Ϣ�޸� htmlname = username
			System.out.println(b.getHtmlname());


			//�޸���ҳ�Լ��Ŀ�
			html h = htmlMap.get(username);
			h.setBoardname(temp[0]);
			valid = temp[1];
		}else if("2".equals(usertype)) {

			valid = str;

		}


		//���ַ���ת����byte[]
		byte info[] = valid.getBytes();
		System.out.print("info len = "+info.length);
		switch(info[0]>>4) {
			case 1:{
				switch(info[0]&0x0f) {
					case 1:ctrl_register(session);break;
					case 2:ctrl_logout(session);break;
					case 3:{//��ҳ����13˵��Ҫ��¼�ļ� 13+�ļ�·��
						//�����ļ�·��
						//�½�����

						byte filepath[] = new byte[info.length-1];
						for(byte i=1; i<info.length; i++) {
							filepath[i-1] = info[i];
						}
						String filename = new String(filepath); //�ļ�·��
						filePath.put(username, filename);//��ҳ�û��� �� �ļ�·��

						ctrl_file(session,filename, username);break;
					}
					case 4:break;
					case 5:{
						System.out.println("��о���յ������ļ�ָʾ");
						System.out.println(info[0]);
						action_sendFile(session,username);
					} break;//�ɹ�
					case 6:break;												  //ʧ�ܣ�������Ϣ�����²���
					case 7:break;												  //��ʾ�����յ���¼����
					default:break;
				}


			} break;
			case 2:{
				switch(info[0]&0x0f) {
					case 1: action_register();break;
					case 2: action_logout();  break;
					case 3: break;
					case 4: action_flash(str,username);   break;
					case 5:{
						//��������������ļ��ɹ�

						ctrl_flash(session,username);
					}break;
					case 6: break;											//ʧ�ܣ�������Ϣ�����²���
					default : break;
				}
			} break;

			default:break;

		}

	}


	public void close() throws IOException {
		fileIn.close();
		array = null;
	}

}

class Info{

	//header

//	public static final byte info_normal = 0;
//	public static final byte info_success = 1;
//	public static final byte info_fail = 2;

	public static final byte info_html = 1;
	public static final byte info_board = 2;

	public static final byte info_ctrl = 1;
	public static final byte info_data = 2;

	//type
	public static final byte  info_registe	= 1;
	public static final byte  info_logout 	= 2;
	public static final byte  info_sendFile = 3;

	public static final byte  info_flash	= 4;



}


class html{
	private String name;
	private String boardname;
	private Session session;
	public html(String name, String boardname,Session session) {
		this.name = name;
		this.boardname = boardname;
		this.session = session;

	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Session getSession() {
		return session;
	}
	public void setSession(Session session) {
		this.session = session;
	}
	public String getBoardname() {
		return boardname;
	}
	public void setBoardname(String boardname) {
		this.boardname = boardname;
	}

}


class board{
	private String  name;
	private String htmlname;
	private Session session;
	private byte state;
	public board(String name, String htmlname,Session session) {
		this.name = name;
		this.htmlname = htmlname;
		this.session = session;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getHtmlname() {
		return htmlname;
	}
	public void setHtmlname(String htmlname) {
		this.htmlname = htmlname;
	}
	public Session getSession() {
		return session;
	}
	public void setSession(Session session) {
		this.session = session;
	}
	public byte getState() {
		return state;

	}
	public void setState(byte state) {
		this.state = state;
	}


}

//������ҳ�˼���

//���������弯��